---
title: Access Tokens
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

For a LiveKit client to successfully connect to the server, it must pass an access token with the request.

This token encodes the identity of a participant, name of the room, capabilities and permissions. Access tokens are JWT-based and signed with your API secret to prevent forgery.

Since participant identity is unique within the room, each access token can be used only by a single participant.

## Creating a token

<Tabs
  defaultValue="node"
  groupId="server-sdk"
  values={[
    {label: 'Golang', value: 'go'},
    {label: 'Node', value: 'node'},
    {label: 'Ruby', value: 'ruby'},
    {label: 'Other', value: 'other'},
  ]}>
  <TabItem value="node">

```typescript title="TypeScript"
import { AccessToken } from 'livekit-server-sdk';

const roomName = 'name-of-room';
const participantIdentity = 'unique-identity';
const participantName = 'display name';

const at = new AccessToken('api-key', 'secret-key', {
  identity: participantIdentity,
  name: participantName,
});
at.addGrant({ roomJoin: true, room: roomName, canPublish: true, canSubscribe: true });

const token = at.toJwt();
console.log('access token', token);
```

  </TabItem>

  <TabItem value="go">

```go title="Go"
import (
	"time"

	lksdk "github.com/livekit/server-sdk-go"
	"github.com/livekit/protocol/auth"
)

func getJoinToken(apiKey, apiSecret, room, identity string) (string, error) {
    canPublish := true
    canSubscribe := true

	at := auth.NewAccessToken(apiKey, apiSecret)
	grant := &auth.VideoGrant{
		RoomJoin:     true,
		Room:         room,
		CanPublish:   &canPublish,
		CanSubscribe: &canSubscribe,
	}
	at.AddGrant(grant).
		SetIdentity(identity).
    // optional
    SetName("participant-name").
		SetValidFor(time.Hour)

	return at.ToJWT()
}
```

  </TabItem>
  <TabItem value="ruby">

  ```ruby title="Ruby"
  require 'livekit'

  token = LiveKit::AccessToken.new(api_key: 'yourkey', api_secret: 'yoursecret')
  token.identity = 'participant-identity'
  token.name = 'participant-name'
  token.add_grant(roomJoin: true, room: 'room-name')

  puts token.to_jwt
  ```

  </TabItem>
  <TabItem value="other">

  For other platforms, you could either implement token generation yourself or use the `livekit-cli` command.

  Token signing is fairly straight forward, see [js implementation](https://github.com/livekit/server-sdk-js/blob/main/src/AccessToken.ts) as a reference.

  LiveKit CLI is available at https://github.com/livekit/livekit-cli

  </TabItem>

</Tabs>

### Token example

Here's an example of the decoded body of a join token:

```json
{
  "exp": 1621657263,
  "iss": "APIMmxiL8rquKztZEoZJV9Fb",
  "sub": "myidentity",
  "nbf": 1619065263,
  "video": {
    "room": "myroom",
    "roomJoin": true
  },
  "metadata": ""
}
```

We use `iss` to identify the API key, `sub` to indicate participant identity, and `video` to encode LiveKit VideoGrant.

## Room permissions

Room permissions are specified in the `video` field of a decoded join token. It may contain one or more of the following properties:

| field        | type   | description                                               |
| :----------- | :----- | :-------------------------------------------------------- |
| roomCreate   | bool   | permission to create rooms                                |
| roomList     | bool   | permission to list available rooms                        |
| roomJoin     | bool   | permission to join a room                                 |
| roomAdmin    | bool   | permission to moderate a room                             |
| room         | string | name of the room, required if join or admin is set        |
| canPublish   | bool   | allow participant to publish tracks                       |
| canPublishData | bool   | allow participant to publish data to the room           |
| canSubscribe | bool   | allow participant to subscribe to tracks                  |
| hidden       | bool   | hide participant from others (used by recorder)           |

### Example: subscribe-only token

To create a token where the participant can only subscribe, and not publish into the room, you would use the following grant:

```json
{
  ...
  "video": {
    "room": "myroom",
    "roomJoin": true,
    "canSubscribe": true,
    "canPublish": false,
    "canPublishData": false
  }
}
```

## Token expiration

A tokens has an expiration time. We recommend setting it to the expected duration of a session. A LiveKit client will store a token for the entire session duration, in case it needs to reconnect.

## Participant metadata

You may also attach any arbirary metadata onto each participant via the `metadata` field. This data is opaque to LiveKit.

When provided, LiveKit will attach the metadata to the participant object that the clients would receive.
